package com.metaverse.backend.task;

import com.metaverse.backend.domain.PlayerData;
import com.metaverse.backend.douyin.PlayerDataDTO;
import com.metaverse.backend.repo.PlayerDataRepo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * 定时更新token
 */
@Slf4j
@AllArgsConstructor
@Service
public class PlayerSaveTask {

    private PlayerDataRepo playerDataRepo;


    private RedisTemplate redisTemplate;
    /**
     * 5秒执行一次
     *
     */
    @Scheduled(fixedDelay = 5L * 1000L)
    public void autoSave(){
        save();
    }


    public void save() {
        int i =0;
        while (Constant.roomlist.size() > 0) {
            String dataMapKey = Constant.
                    roomlist.poll();
            if (dataMapKey != null) {
                save( dataMapKey);
                i++;
            }
        }
        if (i>0){
            log.info("游戏结束，同步玩家数据：{}", i);
        }
    }




    /**
     * 从Redis中获取玩家数据并保存到数据库
     * 此方法首先从Redis中获取所有玩家数据，然后遍历每个玩家的数据，更新或创建玩家信息，
     * 并在满足一定条件时批量保存到数据库，最后记录日志信息
     *
     * @param dataMapKey Redis中存储玩家数据的哈希表键名
     */
    public void save(String dataMapKey) {

        // 计数器，用于统计保存的玩家数据数量
        AtomicInteger saveCount = new AtomicInteger();
        // 存储待保存的玩家数据列表
        List<PlayerData> playerDataList = new ArrayList<>();

        // 从Redis中获取所有玩家数据
        List<Object> list = redisTemplate.opsForHash().values(dataMapKey);
        list.forEach(obj -> {
            // 将Redis中的数据转换为PlayerDataDTO对象
            PlayerDataDTO item = (PlayerDataDTO)obj;
            // 根据sec_openid查找数据库中已存在的玩家数据
            PlayerData playerData = playerDataRepo.findBySecOpenid(item.getSec_openid()).orElse(null);
            if(playerData == null){
                // 如果数据库中不存在该玩家数据，则创建新的PlayerData对象
                playerData = new PlayerData();
                playerData.setSec_openid(item.getSec_openid());
            }
            // 更新玩家数据
            playerData.setAvatar_url(item.getAvatar_url());
            playerData.setNickname(item.getNickname());
            playerData.setPreWorldRank(Long.parseLong(item.getPreWorldRank().toString()));
            playerData.setWorldRank(Long.parseLong(item.getWorldRank().toString()));
            playerData.setScore(item.getScore());
            playerData.setAllscore(item.getAllscore());
            // 初始化或更新玩家的参与次数
            if(playerData.getJoinTimes() == null){
                playerData.setJoinTimes(0L);
            }
            playerData.setJoinTimes(playerData.getJoinTimes() + 1);
            // 初始化或更新玩家的胜利次数
            if(playerData.getVictoryTimes() == null){
                playerData.setVictoryTimes(0L);
            }
            // 如果玩家在当前数据中的排名为第一，则增加胜利次数
            if(item.getRank()==1){
                playerData.setVictoryTimes(playerData.getVictoryTimes() + 1);
            }

            // 将更新后的玩家数据添加到待保存列表中
            playerDataList.add(playerData);

            // 当待保存的玩家数据达到500条时，批量保存到数据库，并清空待保存列表
            if(playerDataList.size() >= 500){
                saveCount.addAndGet(playerDataList.size());
                playerDataRepo.saveAll(playerDataList);
                playerDataList.clear();
            }
        });

        // 如果还有未保存的玩家数据，则进行保存，并记录日志信息
        if(playerDataList.size() > 0){
            saveCount.addAndGet(playerDataList.size());
            playerDataRepo.saveAll(playerDataList);
            playerDataList.clear();
            log.info("同步玩家数据结果：{}, 数量：{}" , dataMapKey, saveCount);
        }
    }

}
